using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Xml;
using System.Xml.XPath;
namespace Net35.Xrm.Sdk.Client
{
	internal sealed class AuthenticationPolicyImporter : System.ServiceModel.Description.IPolicyImportExtension
	{
		internal const string MsXrm = "ms-xrm";
		internal const string MsXrmSecureTokenServiceMsXrmIdentifier = "//ms-xrm:SecureTokenService/ms-xrm:Identifier";
		internal const string MsXrmLiveTrust = "//ms-xrm:LiveTrust/";
		internal const string MsXrmOrgTrust = "//ms-xrm:OrgTrust/";
		internal const string AuthenticationPolicy = "AuthenticationPolicy";
		internal const string LivePartnerIdentifier = "LivePartnerIdentifier";
		internal const string AppliesTo = "AppliesTo";
		internal const string TrustVersion = "TrustVersion";
		internal const string SecurityMode = "SecurityMode";
		internal const string LivePolicy = "LivePolicy";
		internal const string AuthenticationType = "AuthenticationType";
		internal const string SecureTokenServiceIdentifier = "SecureTokenServiceIdentifier";
		internal const string LiveIdAppliesTo = "LiveIdAppliesTo";
		internal const string LiveTrustTrustVersion = "LiveTrustTrustVersion";
		internal const string LiveTrustSecurityMode = "LiveTrustSecurityMode";
		internal const string LiveTrustLivePolicy = "LiveTrustLivePolicy";
		internal const string LiveTrustLiveIdAppliesTo = "LiveTrustLiveIdAppliesTo";
		internal const string LiveEndpoint = "LiveEndpoint";
		internal const string OrgIdAppliesTo = "OrgIdAppliesTo";
		internal const string OrgIdTrustVersion = "OrgIdTrustVersion";
		internal const string OrgIdSecurityMode = "OrgIdSecurityMode";
		internal const string OrgIdPolicy = "OrgIdPolicy";
		internal const string OrgIdDeviceAppliesTo = "OrgIdDeviceAppliesTo";
		internal const string OrgIdEndpoint = "OrgIdEndpoint";
		internal const string Identifier = "Identifier";
		internal const string OrgIdIdentifier = "OrgIdIdentifier";
		internal readonly string MsXrmAuthentication = "//ms-xrm:Authentication";
		private readonly System.ServiceModel.Description.IPolicyImportExtension _importer;
		private readonly object _lockObject = new object();
		public AuthenticationPolicyImporter(System.ServiceModel.Channels.SecurityBindingElementImporter importer)
		{
			this._importer = importer;
		}
		public void ImportPolicy(System.ServiceModel.Description.MetadataImporter importer, System.ServiceModel.Description.PolicyConversionContext context)
		{
			this.ImportXrmAuthenticationPolicy(context);
			this.ImportSecurityPolicy(importer, context);
		}
		private bool ImportPolicyLegacy(System.ServiceModel.Description.PolicyConversionContext context)
		{
			this.ImportFailoverPolicy(context);
			System.Xml.XmlElement xmlElement = context.GetBindingAssertions().Find("AuthenticationPolicy", "http://schemas.microsoft.com/xrm/2011/Contracts/Services");
			if (xmlElement != null)
			{
				bool flag = true;
				AuthenticationPolicy authenticationPolicy = context.BindingElements.Find<AuthenticationPolicy>();
				if (authenticationPolicy == null)
				{
					authenticationPolicy = new AuthenticationPolicy();
					context.BindingElements.Insert(0, authenticationPolicy);
				}
				else if (authenticationPolicy.PolicyElements.ContainsKey("OrgIdAppliesTo"))
				{
					flag = false;
				}
				context.GetBindingAssertions().Remove(xmlElement);
				if (flag)
				{
					System.Xml.XPath.XPathNavigator xPathNavigator = xmlElement.CreateNavigator();
					if (xPathNavigator != null)
					{
						System.Xml.XmlNamespaceManager xmlNamespaceManager = new System.Xml.XmlNamespaceManager(xPathNavigator.NameTable);
						xmlNamespaceManager.AddNamespace("ms-xrm", "http://schemas.microsoft.com/xrm/2011/Contracts/Services");
						AuthenticationPolicyImporter.ExtractValue(authenticationPolicy, xPathNavigator, xmlNamespaceManager, this.MsXrmAuthentication, "AuthenticationType");
						AuthenticationPolicyImporter.ExtractValue(authenticationPolicy, xPathNavigator, xmlNamespaceManager, "//ms-xrm:SecureTokenService/ms-xrm:Identifier", "SecureTokenServiceIdentifier");
						AuthenticationPolicyImporter.ExtractLiveTrustElements(authenticationPolicy, xPathNavigator, xmlNamespaceManager);
					}
				}
				return true;
			}
			return false;
		}
		private bool ImportFailoverPolicy(System.ServiceModel.Description.PolicyConversionContext context)
		{
			System.Xml.XmlElement xmlElement = context.GetBindingAssertions().Find("FailoverPolicy", "http://schemas.microsoft.com/xrm/2012/Contracts/Services");
			if (xmlElement != null)
			{
				bool flag = true;
				FailoverPolicy failoverPolicy = context.BindingElements.Find<FailoverPolicy>();
				if (failoverPolicy == null)
				{
					failoverPolicy = new FailoverPolicy();
					context.BindingElements.Insert(0, failoverPolicy);
				}
				context.GetBindingAssertions().Remove(xmlElement);
				if (flag)
				{
					System.Xml.XPath.XPathNavigator xPathNavigator = xmlElement.CreateNavigator();
					if (xPathNavigator != null)
					{
						System.Xml.XmlNamespaceManager xmlNamespaceManager = new System.Xml.XmlNamespaceManager(xPathNavigator.NameTable);
						xmlNamespaceManager.AddNamespace("ms-xrm", "http://schemas.microsoft.com/xrm/2012/Contracts/Services");
						AuthenticationPolicyImporter.ExtractValue(failoverPolicy, xPathNavigator, xmlNamespaceManager, "ms-xrm:FailoverAvailable", "FailoverAvailable");
						AuthenticationPolicyImporter.ExtractValue(failoverPolicy, xPathNavigator, xmlNamespaceManager, "ms-xrm:EndpointEnabled", "EndpointEnabled");
					}
				}
				return true;
			}
			return false;
		}
		private void ImportXrmAuthenticationPolicy(System.ServiceModel.Description.PolicyConversionContext context)
		{
			bool flag = this.ImportPolicyLegacy(context);
			this.ImportFailoverPolicy(context);
			System.Xml.XmlElement xmlElement = context.GetBindingAssertions().Find("AuthenticationPolicy", "http://schemas.microsoft.com/xrm/2012/Contracts/Services");
			if (xmlElement != null)
			{
				AuthenticationPolicy authenticationPolicy = context.BindingElements.Find<AuthenticationPolicy>();
				string value = null;
				if (authenticationPolicy == null || flag)
				{
					if (flag)
					{
						context.BindingElements.Remove(authenticationPolicy);
					}
					if (authenticationPolicy != null)
					{
						authenticationPolicy.PolicyElements.TryGetValue("AppliesTo", out value);
					}
					authenticationPolicy = new AuthenticationPolicy();
					if (!StringExtensions.IsNullOrWhiteSpace(value))
					{
						authenticationPolicy.PolicyElements.Add("LivePartnerIdentifier", value);
					}
					context.BindingElements.Insert(0, authenticationPolicy);
				}
				context.GetBindingAssertions().Remove(xmlElement);
				System.Xml.XPath.XPathNavigator xPathNavigator = xmlElement.CreateNavigator();
				if (xPathNavigator != null)
				{
					System.Xml.XmlNamespaceManager xmlNamespaceManager = new System.Xml.XmlNamespaceManager(xPathNavigator.NameTable);
					xmlNamespaceManager.AddNamespace("ms-xrm", "http://schemas.microsoft.com/xrm/2012/Contracts/Services");
					AuthenticationPolicyImporter.ExtractValue(authenticationPolicy, xPathNavigator, xmlNamespaceManager, this.MsXrmAuthentication, "AuthenticationType");
					AuthenticationPolicyImporter.ExtractValue(authenticationPolicy, xPathNavigator, xmlNamespaceManager, "//ms-xrm:SecureTokenService/ms-xrm:Identifier", "SecureTokenServiceIdentifier");
					AuthenticationPolicyImporter.ExtractLiveTrustElements(authenticationPolicy, xPathNavigator, xmlNamespaceManager);
					AuthenticationPolicyImporter.ExtractOrgTrustElements(authenticationPolicy, xPathNavigator, xmlNamespaceManager);
				}
			}
		}
		private static void ExtractLiveTrustElements(AuthenticationPolicy xrmPolicyBindingElement, System.Xml.XPath.XPathNavigator navigator, System.Xml.XmlNamespaceManager nsmgr)
		{
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:LiveTrust/ms-xrm:AppliesTo", "AppliesTo");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:LiveTrust/ms-xrm:TrustVersion", "LiveTrustTrustVersion");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:LiveTrust/ms-xrm:SecurityMode", "LiveTrustSecurityMode");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:LiveTrust/ms-xrm:LivePolicy", "LiveTrustLivePolicy");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:LiveTrust/ms-xrm:LiveIdAppliesTo", "LiveTrustLiveIdAppliesTo");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:LiveTrust/ms-xrm:LiveEndpoint", "LiveEndpoint");
		}
		private static void ExtractOrgTrustElements(AuthenticationPolicy xrmPolicyBindingElement, System.Xml.XPath.XPathNavigator navigator, System.Xml.XmlNamespaceManager nsmgr)
		{
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:AppliesTo", "OrgIdAppliesTo");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:TrustVersion", "OrgIdTrustVersion");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:SecurityMode", "OrgIdSecurityMode");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:LivePolicy", "OrgIdPolicy");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:LiveIdAppliesTo", "OrgIdDeviceAppliesTo");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:LiveEndpoint", "OrgIdEndpoint");
			AuthenticationPolicyImporter.ExtractValue(xrmPolicyBindingElement, navigator, nsmgr, "//ms-xrm:OrgTrust/ms-xrm:Identifier", "OrgIdIdentifier");
		}
		private static void ExtractValue(XrmPolicy xrmPolicy, System.Xml.XPath.XPathNavigator navigator, System.Xml.XmlNamespaceManager nsmgr, string query, string name)
		{
			System.Xml.XPath.XPathNavigator xPathNavigator = navigator.SelectSingleNode(query, nsmgr);
			if (xPathNavigator != null)
			{
				xrmPolicy.PolicyElements[name] = xPathNavigator.Value;
			}
		}
		private void ImportSecurityPolicy(System.ServiceModel.Description.MetadataImporter metadataImporter, System.ServiceModel.Description.PolicyConversionContext context)
		{
			bool flag = true;
			AuthenticationPolicy authenticationPolicy = context.BindingElements.Find<AuthenticationPolicy>();
			if (authenticationPolicy != null && authenticationPolicy.PolicyElements.ContainsKey("AuthenticationType"))
			{
				string value = authenticationPolicy.PolicyElements["AuthenticationType"];
				AuthenticationProviderType authenticationProviderType;
				if (EnumExtensions.TryParse<AuthenticationProviderType>(value, out authenticationProviderType))
				{
					flag = (authenticationProviderType != AuthenticationProviderType.OnlineFederation && authenticationProviderType != AuthenticationProviderType.LiveId);
				}
			}
			if (this._importer != null)
			{
				if (flag)
				{
					this._importer.ImportPolicy(metadataImporter, context);
					return;
				}
				this.ImportSecurityPolicyWithoutMetadata(metadataImporter, context);
			}
		}
		private void ImportSecurityPolicyWithoutMetadata(System.ServiceModel.Description.MetadataImporter metadataImporter, System.ServiceModel.Description.PolicyConversionContext context)
		{
			System.ServiceModel.Description.MetadataExchangeClient metadataExchangeClient = new System.ServiceModel.Description.MetadataExchangeClient(new System.ServiceModel.EndpointAddress(new System.Uri("http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self"), new System.ServiceModel.Channels.AddressHeader[0]));
			metadataExchangeClient.ResolveMetadataReferences = false;
			lock (this._lockObject)
			{
				try
				{
					if (metadataImporter.State != null)
					{
						metadataImporter.State["MetadataExchangeClientKey"] = metadataExchangeClient;
					}
					this._importer.ImportPolicy(metadataImporter, context);
				}
				finally
				{
					if (metadataImporter.State != null)
					{
						metadataImporter.State.Remove("MetadataExchangeClientKey");
					}
				}
			}
		}
	}
}
